#include <cstddef>
#include <cstdint>
#include <stdint.h>

struct ErrorMsg {
  size_t handle;
};

struct ComplexF64 {
  double real;
  double imag;
};

typedef struct ErrorMsg ErrorMsg;
typedef struct ComplexF64 ComplexF64;

struct CDatum {
  int64_t _payload1;
  int64_t _payload2;
};

typedef struct CDatum CDatum;

#if defined(__cplusplus)
extern "C" {
#endif

/* ============================  Tensor Ops ============================== */
// get the data, in the readonly way
//
// NOTE: if you are to modify the data, please use `tonglun_tensor_mutable_data`
ErrorMsg tonglun_tensor_readonly_data(
    /* out */ const void **out_data,
    /* in */ CDatum tensor);

// get the data, in the mutable way
//
// NOTE:
// 1. this will assure the returned pointer is only owned by the caller
// 2. if the tensor is owned by 2 or more parties, return an error
ErrorMsg tonglun_tensor_mutable_data(
    /* out */ void **out_data,
    /* in */ CDatum tensor);

// get the shape pointer
ErrorMsg tonglun_tensor_shape(
    /* out */ size_t **out_shape,
    /* in */ CDatum tensor);

// get the strides pointer
ErrorMsg tonglun_tensor_strides(
    /* out */ size_t **out_strides,
    /* in */ CDatum tensor);

// total number of elements in a tensor
ErrorMsg tonglun_tensor_numel(
    /* out */ size_t *out,
    /* in */ CDatum tensor);

// the size of a given diemnsion axis in a tensor
ErrorMsg tonglun_tensor_size(
    /* out */ size_t *out,
    /* in */ CDatum tensor,
    /* in */ size_t axis);

/* ================================= Ops ================================= */

// len(list)
ErrorMsg tonglun_ops_list_len(
    /* out */ size_t *out,
    /* in */ CDatum list);

// list[i]
ErrorMsg tonglun_ops_list_loadi(
    /* out */ CDatum *out,
    /* in */ CDatum list,
    /* in */ size_t i);

// load string data
ErrorMsg tonglun_ops_str_load(
    /* out */ char **str_ptr,
    /* out */ size_t *str_len,
    /* in */ CDatum str);

// load int data
ErrorMsg tonglun_ops_bool_load(
    /* out */ bool *out,
    /* in */ CDatum val);

ErrorMsg tonglun_ops_complex64_load(
    /* out */ ComplexF64 *real,
    /* in */ CDatum val);

ErrorMsg tonglun_ops_f64_load(
    /* out */ double *out,
    /* in */ CDatum val);

ErrorMsg tonglun_ops_i64_load(
    /* out */ int64_t *out,
    /* in */ CDatum val);

#if defined(__cplusplus)
}
#endif